home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / prog / dflt18.arj / LISTBOX.C < prev    next >
Text File  |  1994-02-07  |  14KB  |  473 lines

  1. /* ------------- listbox.c ------------ */
  2.  
  3. #include "dflat.h"
  4.  
  5. #ifdef INCLUDE_EXTENDEDSELECTIONS
  6. static int ExtendSelections(WINDOW, int, int);
  7. static void TestExtended(WINDOW, PARAM);
  8. static void ClearAllSelections(WINDOW);
  9. static void SetSelection(WINDOW, int);
  10. static void FlipSelection(WINDOW, int);
  11. static void ClearSelection(WINDOW, int);
  12. #else
  13. #define TestExtended(w,p) /**/
  14. #endif
  15. static void near ChangeSelection(WINDOW, int, int);
  16. static void near WriteSelection(WINDOW, int, int, RECT *);
  17. static BOOL SelectionInWindow(WINDOW, int);
  18.  
  19. static int py = -1;    /* the previous y mouse coordinate */
  20.  
  21. #ifdef INCLUDE_EXTENDEDSELECTIONS
  22. /* --------- SHIFT_F8 Key ------------ */
  23. static void AddModeKey(WINDOW wnd)
  24. {
  25.     if (isMultiLine(wnd))    {
  26.         wnd->AddMode ^= TRUE;
  27.         SendMessage(GetParent(wnd), ADDSTATUS,
  28.             wnd->AddMode ? ((PARAM) "Add Mode") : 0, 0);
  29.     }
  30. }
  31. #endif
  32.  
  33. /* --------- UP (Up Arrow) Key ------------ */
  34. static void UpKey(WINDOW wnd, PARAM p2)
  35. {
  36.     if (wnd->selection > 0)    {
  37.         if (wnd->selection == wnd->wtop)    {
  38.             BaseWndProc(LISTBOX, wnd, KEYBOARD, UP, p2);
  39.             PostMessage(wnd, LB_SELECTION, wnd->selection-1,
  40.                 isMultiLine(wnd) ? p2 : FALSE);
  41.         }
  42.         else    {
  43.             int newsel = wnd->selection-1;
  44.             if (wnd->wlines == ClientHeight(wnd))
  45.                 while (*TextLine(wnd, newsel) == LINE)
  46.                     --newsel;
  47.             PostMessage(wnd, LB_SELECTION, newsel,
  48. #ifdef INCLUDE_EXTENDEDSELECTIONS
  49.                 isMultiLine(wnd) ? p2 :
  50. #endif
  51.                 FALSE);
  52.         }
  53.     }
  54. }
  55.  
  56. /* --------- DN (Down Arrow) Key ------------ */
  57. static void DnKey(WINDOW wnd, PARAM p2)
  58. {
  59.     if (wnd->selection < wnd->wlines-1)    {
  60.         if (wnd->selection == wnd->wtop+ClientHeight(wnd)-1)  {
  61.             BaseWndProc(LISTBOX, wnd, KEYBOARD, DN, p2);
  62.             PostMessage(wnd, LB_SELECTION, wnd->selection+1,
  63.                 isMultiLine(wnd) ? p2 : FALSE);
  64.         }
  65.         else    {
  66.             int newsel = wnd->selection+1;
  67.             if (wnd->wlines == ClientHeight(wnd))
  68.                 while (*TextLine(wnd, newsel) == LINE)
  69.                     newsel++;
  70.             PostMessage(wnd, LB_SELECTION, newsel,
  71. #ifdef INCLUDE_EXTENDEDSELECTIONS
  72.                 isMultiLine(wnd) ? p2 :
  73. #endif
  74.                 FALSE);
  75.         }
  76.     }
  77. }
  78.  
  79. /* --------- HOME and PGUP Keys ------------ */
  80. static void HomePgUpKey(WINDOW wnd, PARAM p1, PARAM p2)
  81. {
  82.     BaseWndProc(LISTBOX, wnd, KEYBOARD, p1, p2);
  83.     PostMessage(wnd, LB_SELECTION, wnd->wtop,
  84. #ifdef INCLUDE_EXTENDEDSELECTIONS
  85.         isMultiLine(wnd) ? p2 :
  86. #endif
  87.         FALSE);
  88. }
  89.  
  90. /* --------- END and PGDN Keys ------------ */
  91. static void EndPgDnKey(WINDOW wnd, PARAM p1, PARAM p2)
  92. {
  93.     int bot;
  94.     BaseWndProc(LISTBOX, wnd, KEYBOARD, p1, p2);
  95.     bot = wnd->wtop+ClientHeight(wnd)-1;
  96.     if (bot > wnd->wlines-1)
  97.         bot = wnd->wlines-1;
  98.     PostMessage(wnd, LB_SELECTION, bot,
  99. #ifdef INCLUDE_EXTENDEDSELECTIONS
  100.         isMultiLine(wnd) ? p2 :
  101. #endif
  102.         FALSE);
  103. }
  104.  
  105. #ifdef INCLUDE_EXTENDEDSELECTIONS
  106. /* --------- Space Bar Key ------------ */
  107. static void SpacebarKey(WINDOW wnd, PARAM p2)
  108. {
  109.     if (isMultiLine(wnd))    {
  110.         int sel = SendMessage(wnd, LB_CURRENTSELECTION, 0, 0);
  111.         if (sel != -1)    {
  112.             if (wnd->AddMode)
  113.                 FlipSelection(wnd, sel);
  114.             if (ItemSelected(wnd, sel))    {
  115.                 if (!((int) p2 & (LEFTSHIFT | RIGHTSHIFT)))
  116.                     wnd->AnchorPoint = sel;
  117.                 ExtendSelections(wnd, sel, (int) p2);
  118.             }
  119.             else
  120.                 wnd->AnchorPoint = -1;
  121.             SendMessage(wnd, PAINT, 0, 0);
  122.         }
  123.     }
  124. }
  125. #endif
  126.  
  127. /* --------- Enter ('\r') Key ------------ */
  128. static void EnterKey(WINDOW wnd)
  129. {
  130.     if (wnd->selection != -1)    {
  131.         SendMessage(wnd, LB_SELECTION, wnd->selection, TRUE);
  132.         SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
  133.     }
  134. }
  135.  
  136. /* --------- All Other Key Presses ------------ */
  137. static void KeyPress(WINDOW wnd, PARAM p1, PARAM p2)
  138. {
  139.     int sel = wnd->selection+1;
  140.     while (sel < wnd->wlines)    {
  141.         char *cp = TextLine(wnd, sel);
  142.         if (cp == NULL)
  143.             break;
  144. #ifdef INCLUDE_EXTENDEDSELECTIONS
  145.         if (isMultiLine(wnd))
  146.             cp++;
  147. #endif
  148.         if (tolower(*cp) == (int)p1)    {
  149.             SendMessage(wnd, LB_SELECTION, sel,
  150.                 isMultiLine(wnd) ? p2 : FALSE);
  151.             if (!SelectionInWindow(wnd, sel))    {
  152.                 wnd->wtop = sel-ClientHeight(wnd)+1;
  153.                 SendMessage(wnd, PAINT, 0, 0);
  154.             }
  155.             break;
  156.         }
  157.         sel++;
  158.     }
  159. }
  160.  
  161. /* --------- KEYBOARD Message ------------ */
  162. static int KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  163. {
  164.     switch ((int) p1)    {
  165. #ifdef INCLUDE_EXTENDEDSELECTIONS
  166.         case SHIFT_F8:
  167.             AddModeKey(wnd);
  168.             return TRUE;
  169. #endif
  170.         case UP:
  171.             TestExtended(wnd, p2);
  172.             UpKey(wnd, p2);
  173.             return TRUE;
  174.         case DN:
  175.             TestExtended(wnd, p2);
  176.             DnKey(wnd, p2);
  177.             return TRUE;
  178.         case PGUP:
  179.         case HOME:
  180.             TestExtended(wnd, p2);
  181.             HomePgUpKey(wnd, p1, p2);
  182.             return TRUE;
  183.         case PGDN:
  184.         case END:
  185.             TestExtended(wnd, p2);
  186.             EndPgDnKey(wnd, p1, p2);
  187.             return TRUE;
  188. #ifdef INCLUDE_EXTENDEDSELECTIONS
  189.         case ' ':
  190.             SpacebarKey(wnd, p2);
  191.             break;
  192. #endif
  193.         case '\r':
  194.             EnterKey(wnd);
  195.             return TRUE;
  196.         default:
  197.             KeyPress(wnd, p1, p2);
  198.             break;
  199.     }
  200.     return FALSE;
  201. }
  202.  
  203. /* ------- LEFT_BUTTON Message -------- */
  204. static int LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  205. {
  206.     int my = (int) p2 - GetTop(wnd);
  207.     if (my >= wnd->wlines-wnd->wtop)
  208.         my = wnd->wlines - wnd->wtop;
  209.  
  210.     if (!InsideRect(p1, p2, ClientRect(wnd)))
  211.         return FALSE;
  212.     if (wnd->wlines && my != py)    {
  213.         int sel = wnd->wtop+my-1;
  214. #ifdef INCLUDE_EXTENDEDSELECTIONS
  215.         int sh = getshift();
  216.         if (!(sh & (LEFTSHIFT | RIGHTSHIFT)))    {
  217.             if (!(sh & CTRLKEY))
  218.                 ClearAllSelections(wnd);
  219.             wnd->AnchorPoint = sel;
  220.             SendMessage(wnd, PAINT, 0, 0);
  221.         }
  222. #endif
  223.         SendMessage(wnd, LB_SELECTION, sel, TRUE);
  224.         py = my;
  225.     }
  226.     return TRUE;
  227. }
  228.  
  229. /* ------------- DOUBLE_CLICK Message ------------ */
  230. static int DoubleClickMsg(WINDOW wnd, PARAM p1, PARAM p2)
  231. {
  232.     if (WindowMoving || WindowSizing)
  233.         return FALSE;
  234.     if (wnd->wlines)    {
  235.         RECT rc = ClientRect(wnd);
  236.         BaseWndProc(LISTBOX, wnd, DOUBLE_CLICK, p1, p2);
  237.         if (InsideRect(p1, p2, rc))
  238.             SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
  239.     }
  240.     return TRUE;
  241. }
  242.  
  243. /* ------------ ADDTEXT Message -------------- */
  244. static int AddTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  245. {
  246.     int rtn = BaseWndProc(LISTBOX, wnd, ADDTEXT, p1, p2);
  247.     if (wnd->selection == -1)
  248.         SendMessage(wnd, LB_SETSELECTION, 0, 0);
  249. #ifdef INCLUDE_EXTENDEDSELECTIONS
  250.     if (*(char *)p1 == LISTSELECTOR)
  251.         wnd->SelectCount++;
  252. #endif
  253.     return rtn;
  254. }
  255.  
  256. /* --------- GETTEXT Message ------------ */
  257. static void GetTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  258. {
  259.     if ((int)p2 != -1)    {
  260.         char *cp1 = (char *)p1;
  261.         char *cp2 = TextLine(wnd, (int)p2);
  262.         while (cp2 && *cp2 && *cp2 != '\n')
  263.             *cp1++ = *cp2++;
  264.         *cp1 = '\0';
  265.     }
  266. }
  267.  
  268. /* --------- LISTBOX Window Processing Module ------------ */
  269. int ListBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  270. {
  271.     switch (msg)    {
  272.         case CREATE_WINDOW:
  273.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  274.             wnd->selection = -1;
  275. #ifdef INCLUDE_EXTENDEDSELECTIONS
  276.             wnd->AnchorPoint = -1;
  277. #endif
  278.             return TRUE;
  279.         case KEYBOARD:
  280.             if (WindowMoving || WindowSizing)
  281.                 break;
  282.             if (KeyboardMsg(wnd, p1, p2))
  283.                 return TRUE;
  284.             break;
  285.         case LEFT_BUTTON:
  286.             if (LeftButtonMsg(wnd, p1, p2) == TRUE)
  287.                 return TRUE;
  288.             break;
  289.         case DOUBLE_CLICK:
  290.             if (DoubleClickMsg(wnd, p1, p2))
  291.                 return TRUE;
  292.             break;
  293.         case BUTTON_RELEASED:
  294.             if (WindowMoving || WindowSizing || VSliding)
  295.                 break;
  296.             py = -1;
  297.             return TRUE;
  298.         case ADDTEXT:
  299.             return AddTextMsg(wnd, p1, p2);
  300.         case LB_GETTEXT:
  301.             GetTextMsg(wnd, p1, p2);
  302.             return TRUE;
  303.         case CLEARTEXT:
  304.             wnd->selection = -1;
  305. #ifdef INCLUDE_EXTENDEDSELECTIONS
  306.             wnd->AnchorPoint = -1;
  307. #endif
  308.             wnd->SelectCount = 0;
  309.             break;
  310.         case PAINT:
  311.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  312.             if (wnd == inFocus)
  313.                 WriteSelection(wnd, wnd->selection, TRUE, (RECT *)p1);
  314.             return TRUE;
  315.         case SETFOCUS:
  316.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  317.             WriteSelection(wnd, wnd->selection, p1, NULL);
  318.             return TRUE;
  319.         case SCROLL:
  320.         case HORIZSCROLL:
  321.         case SCROLLPAGE:
  322.         case HORIZPAGE:
  323.         case SCROLLDOC:
  324.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  325.             WriteSelection(wnd,wnd->selection,TRUE,NULL);
  326.             return TRUE;
  327.         case LB_CHOOSE:
  328.             SendMessage(GetParent(wnd), LB_CHOOSE, p1, p2);
  329.             return TRUE;
  330.         case LB_SELECTION:
  331.             ChangeSelection(wnd, (int) p1, (int) p2);
  332.             SendMessage(GetParent(wnd), LB_SELECTION,
  333.                 wnd->selection, 0);
  334.             return TRUE;
  335.         case LB_CURRENTSELECTION:
  336.             return wnd->selection;
  337.         case LB_SETSELECTION:
  338.             ChangeSelection(wnd, (int) p1, 0);
  339.             return TRUE;
  340. #ifdef INCLUDE_EXTENDEDSELECTIONS
  341.         case CLOSE_WINDOW:
  342.             if (isMultiLine(wnd) && wnd->AddMode)    {
  343.                 wnd->AddMode = FALSE;
  344.                 SendMessage(GetParent(wnd), ADDSTATUS, 0, 0);
  345.             }
  346.             break;
  347. #endif
  348.         default:
  349.             break;
  350.     }
  351.     return BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  352. }
  353.  
  354. static BOOL SelectionInWindow(WINDOW wnd, int sel)
  355. {
  356.     return (wnd->wlines && sel >= wnd->wtop &&
  357.             sel < wnd->wtop+ClientHeight(wnd));
  358. }
  359.  
  360. static void near WriteSelection(WINDOW wnd, int sel,
  361.                                     int reverse, RECT *rc)
  362. {
  363.     if (isVisible(wnd))
  364.         if (SelectionInWindow(wnd, sel))
  365.             WriteTextLine(wnd, rc, sel, reverse);
  366. }
  367.  
  368. #ifdef INCLUDE_EXTENDEDSELECTIONS
  369. /* ----- Test for extended selections in the listbox ----- */
  370. static void TestExtended(WINDOW wnd, PARAM p2)
  371. {
  372.     if (isMultiLine(wnd) && !wnd->AddMode &&
  373.             !((int) p2 & (LEFTSHIFT | RIGHTSHIFT)))    {
  374.         if (wnd->SelectCount > 1)    {
  375.             ClearAllSelections(wnd);
  376.             SendMessage(wnd, PAINT, 0, 0);
  377.         }
  378.     }
  379. }
  380.  
  381. /* ----- Clear selections in the listbox ----- */
  382. static void ClearAllSelections(WINDOW wnd)
  383. {
  384.     if (isMultiLine(wnd) && wnd->SelectCount > 0)    {
  385.         int sel;
  386.         for (sel = 0; sel < wnd->wlines; sel++)
  387.             ClearSelection(wnd, sel);
  388.     }
  389. }
  390.  
  391. /* ----- Invert a selection in the listbox ----- */
  392. static void FlipSelection(WINDOW wnd, int sel)
  393. {
  394.     if (isMultiLine(wnd))    {
  395.         if (ItemSelected(wnd, sel))
  396.             ClearSelection(wnd, sel);
  397.         else
  398.             SetSelection(wnd, sel);
  399.     }
  400. }
  401.  
  402. static int ExtendSelections(WINDOW wnd, int sel, int shift)
  403. {    
  404.     if (shift & (LEFTSHIFT | RIGHTSHIFT) &&
  405.                         wnd->AnchorPoint != -1)    {
  406.         int i = sel;
  407.         int j = wnd->AnchorPoint;
  408.         int rtn;
  409.         if (j > i)
  410.             swap(i,j);
  411.         rtn = i - j;
  412.         while (j <= i)
  413.             SetSelection(wnd, j++);
  414.         return rtn;
  415.     }
  416.     return 0;
  417. }
  418.  
  419. static void SetSelection(WINDOW wnd, int sel)
  420. {
  421.     if (isMultiLine(wnd) && !ItemSelected(wnd, sel))    {
  422.         char *lp = TextLine(wnd, sel);
  423.         *lp = LISTSELECTOR;
  424.         wnd->SelectCount++;
  425.     }
  426. }
  427.  
  428. static void ClearSelection(WINDOW wnd, int sel)
  429. {
  430.     if (isMultiLine(wnd) && ItemSelected(wnd, sel))    {
  431.         char *lp = TextLine(wnd, sel);
  432.         *lp = ' ';
  433.         --wnd->SelectCount;
  434.     }
  435. }
  436.  
  437. BOOL ItemSelected(WINDOW wnd, int sel)
  438. {
  439.     if (sel != -1 && isMultiLine(wnd) && sel < wnd->wlines)    {
  440.         char *cp = TextLine(wnd, sel);
  441.         return (int)((*cp) & 255) == LISTSELECTOR;
  442.     }
  443.     return FALSE;
  444. }
  445. #endif
  446.  
  447. static void near ChangeSelection(WINDOW wnd,int sel,int shift)
  448. {
  449.     if (sel != wnd->selection)    {
  450. #ifdef INCLUDE_EXTENDEDSELECTIONS
  451.         if (isMultiLine(wnd))        {
  452.             int sels;
  453.             if (!wnd->AddMode)
  454.                 ClearAllSelections(wnd);
  455.             sels = ExtendSelections(wnd, sel, shift);
  456.             if (sels > 1)
  457.                 SendMessage(wnd, PAINT, 0, 0);
  458.             if (sels == 0 && !wnd->AddMode)    {
  459.                 ClearSelection(wnd, wnd->selection);
  460.                 SetSelection(wnd, sel);
  461.                 wnd->AnchorPoint = sel;
  462.             }
  463.         }
  464. #endif
  465.         WriteSelection(wnd, wnd->selection, FALSE, NULL);
  466.         wnd->selection = sel;
  467.         WriteSelection(wnd, sel, TRUE, NULL);
  468.      }
  469. }
  470.  
  471.  
  472. 
  473.